/* Gionata Massi <gionata.massi@gmail.com>
 * Febbraio 2007
 *
 * File: memory.cpp
 *
 * Questo file fa parte di 'aga'
 */

/*!
  \file		memory.cpp
  \brief	Solutore MOSP e MOSPk mediante algoritmo genetico.
  \author	Gionata Massi
  \version	2009-07-23
  \date		2007-03-22

  Allocazione e rilascio della memoria.
 */

#include "aga.h"
#include <limits.h>

//! Imposta i parametri di default dell'algoritmo.
/*!
  Rilascia le risorse allocate.

  \param data	Puntatore alla struttura contente i parametri dell'algoritmo
		genetico.
*/
void FreeData(GeneticData * data)
{
	FreePopulation(&data->People);
}

//! Restituisce una popolazione di \p nIndividuals individui
/*!
  Restituisce una popolazione di nIndividuals individui, ognuno dei quali ha
  \p nGenes geni.
  In caso di errore restituisce \p NULL.

  \param nIndividuals	Numero di individui
  \param nGenes		Numero di geni, ovvero di schemi di taglio
  \return 		La popolazione, o NULL in caso di errore
  \sa	FreePopulation()
*/
Population AllocatePopulation(int nIndividuals, int nGenes)
{
	int n;
	/* Allocazione della popolazione */
	/* nIndividuals + 1 con l'ultimo lasciato a NULL affinche'
	 * la funzione FreePopulation abbia una terminazione.
	 * \sa FreePopulation() */

	Population result =
	    (Population) calloc(nIndividuals + 2, sizeof(Individual));

	if (!result)
		exit(1);

	/* Allocazione degli individui */
	for (n = 0; n < nIndividuals + 1; n++) {
		/* Ogni individuo e' codificato dai sui geni, ossia
		 * dalla sequenza degli schemi */
		result[n].Sequence = (Gene *) calloc(nGenes, sizeof(Gene));
		if (!result[n].Sequence) {
			/* L'individuo non e' stato creato... */
			while (n) {
				free(result[--n].Sequence);
			}
			free(result);
			/* Restituisci errore */
			return 0;
		}
//              result[n].Score.openStacks =
//                                  (int *)calloc(nGenes, sizeof(int));
//              if (!result[n].Score.openStacks) {
//                      fprintf(stderr,
//                              "ERRORE: impossibile allocare result[n].Score.openStacks\n");
//                      exit(5);
//              }
		for (int k = 0; k < parameters; k++)
			result[n].Score.measure[k] = 0;
		for (int i = 0; i < LS_TYPES; i++)
			result[n].LS_performed[i] = 0;
	}
	/* metodo piu' veloce, con una sola richiesta di allocazione
	 * dinamica della memoria. */
//              result[0] =
//                  (Individual) calloc(nIndividuals * nGenes, sizeof(Gene));
//              if (!result[0])
//                      return 0;
//              for (n = 1; n < nIndividuals; n++) {
//                      result[n] = result[n - 1] + nGenes;
//              }

	return result;
}

//! Rilascia tutte le risorse allocate per la popolazione \p *pPopulation.
/*!
  \param pPopulation Il puntatore alla popolazione da deallocare.
  \sa AllocatePopulation()
*/
void FreePopulation(Population * pPopulation)
{
	if (pPopulation && *pPopulation) {
		Population p = *pPopulation;
		/* Rilascia gli individui */
		while (p->Sequence) {
			free(p->Sequence);
			p++;
		}

		/* Rilascia ed azzera la popolazione */
		free(*pPopulation);
		*pPopulation = 0;
	}
}

void AllocateIndividual(Individual * ind, int NumGenes)
{
	ind->Sequence = (Gene *) calloc(NumGenes, sizeof(Gene));
	if (!ind->Sequence) {
		exit(1);
	}
	ind->Score.measure[TOTAL_COST] = INT_MAX;
	for (int k = TOTAL_COST + 1; k < parameters; k++)
		ind->Score.measure[k] = 0;
	for (int i = 0; i < LS_TYPES; i++)
		ind->LS_performed[i] = 0;
}

void FreeIndividual(Individual * ind)
{
	if (ind->Sequence)
		free(ind->Sequence);
	ind->Sequence = 0;
	// if (ind->Score.openStacks)
	//      free(ind->Score.openStacks);
	// ind->Score.openStacks = 0;
}
